/**
 * 网络管理器
 * 提供网络状态监控和网络相关工具方法
 */

const logger = require('./logger').logger;
const envDetector = require('./env-detector');

// 节流延迟（毫秒）
const THROTTLE_DELAY = 1000;

// 网络质量等级
const NETWORK_QUALITY = {
  EXCELLENT: 'excellent',  // 优秀：延迟 <100ms
  GOOD: 'good',           // 良好：延迟 100-300ms
  FAIR: 'fair',           // 一般：延迟 300-600ms
  POOR: 'poor',           // 较差：延迟 600-1000ms
  BAD: 'bad'              // 糟糕：延迟 >1000ms 或无法连接
};

/**
 * 网络管理器类
 */
class NetworkManager {
  constructor() {
    this.networkType = 'unknown';
    this.isMonitoring = false;
    this.callbacks = [];
    this.isDevTools = envDetector.isDevTools();
    
    // 网络状态变化计数器
    this.changeCount = 0;
    
    // 最后一次回调时间
    this.lastCallbackTime = 0;
    
    // 网络质量测试数据
    this.qualityTestData = {
      lastTestTime: 0,
      latency: -1,
      quality: NETWORK_QUALITY.FAIR,
      testEndpoints: ['https://www.baidu.com', 'https://www.qq.com'],
      testInterval: 300000, // 5分钟测试一次
      isAutoTesting: false,
      testHistory: [] // 最近的测试历史
    };
    
    // 定时器ID
    this.timers = {
      qualityTest: null
    };
  }

  /**
   * 开始监控网络状态变化
   * @param {Object} options 选项
   * @param {Function} options.onChange 网络状态变化回调
   * @param {boolean} options.enableQualityTest 是否启用质量测试
   * @param {number} options.qualityTestInterval 质量测试间隔（毫秒）
   */
  startMonitoring(options = {}) {
    if (this.isMonitoring) {
      logger.warn('网络状态监控已经在运行中');
      return;
    }
    
    // 记录回调
    if (options.onChange) {
      this.callbacks.push(options.onChange);
    }
    
    // 配置质量测试
    if (options.enableQualityTest !== undefined) {
      this.qualityTestData.isAutoTesting = options.enableQualityTest;
    }
    
    if (options.qualityTestInterval) {
      this.qualityTestData.testInterval = options.qualityTestInterval;
    }
    
    // 标记为监控中
    this.isMonitoring = true;
    
    // 获取当前网络类型
    this._getNetworkType();
    
    // 监听网络状态变化
    wx.onNetworkStatusChange(this._handleNetworkChange.bind(this));
    
    // 如果启用了质量测试，开始定期测试
    if (this.qualityTestData.isAutoTesting) {
      this._startQualityTestTimer();
    }
    
    logger.info('网络状态监控已启动', {
      enableQualityTest: this.qualityTestData.isAutoTesting,
      qualityTestInterval: this.qualityTestData.testInterval
    });
  }

  /**
   * 处理网络状态变化
   * @param {Object} res 网络状态对象
   * @private
   */
  _handleNetworkChange(res) {
    // 增加变化计数
    this.changeCount++;
    
    logger.info('网络状态变化', {
      changeCount: this.changeCount,
      networkType: res.networkType,
      isConnected: res.isConnected
    });
    
    const prevNetworkType = this.networkType;
    const newNetworkType = res.networkType;
    
    // 更新网络类型
    this.networkType = newNetworkType;
    
    // 执行节流处理，避免短时间内多次触发
    const now = Date.now();
    if (now - this.lastCallbackTime < THROTTLE_DELAY) {
      logger.info(`网络状态变化太频繁，${THROTTLE_DELAY}ms内仅触发一次回调`);
      return;
    }
    
    // 更新最后回调时间
    this.lastCallbackTime = now;
    
    // 只有当网络类型真正发生变化时才触发回调
    if (prevNetworkType !== newNetworkType) {
      logger.info(`网络类型从 ${prevNetworkType} 变为 ${newNetworkType}`);
      
      // 如果启用了质量测试并且新网络已连接，立即进行一次测试
      if (this.qualityTestData.isAutoTesting && res.isConnected) {
        this._testNetworkQuality().catch(err => {
          logger.error('网络质量测试失败', err);
        });
      }
      
      // 触发所有回调
      this._triggerCallbacks(newNetworkType, prevNetworkType);
    }
  }

  /**
   * 开始质量测试定时器
   * @private
   */
  _startQualityTestTimer() {
    // 清除旧定时器
    if (this.timers.qualityTest) {
      clearInterval(this.timers.qualityTest);
    }
    
    // 设置新定时器
    this.timers.qualityTest = setInterval(() => {
      // 只在连接可用时测试
      if (this.isConnected()) {
        this._testNetworkQuality().catch(err => {
          logger.error('定期网络质量测试失败', err);
        });
      }
    }, this.qualityTestData.testInterval);
    
    logger.info(`已设置网络质量测试定时器，间隔 ${this.qualityTestData.testInterval}ms`);
  }

  /**
   * 测试网络质量
   * @returns {Promise<Object>} 网络质量测试结果
   * @private
   */
  async _testNetworkQuality() {
    // 如果在开发者工具中，返回模拟数据
    if (this.isDevTools) {
      const quality = {
        latency: Math.floor(Math.random() * 200) + 50,
        success: true,
        timestamp: Date.now()
      };
      
      // 评估质量
      quality.quality = this._evaluateNetworkQuality(quality.latency);
      
      // 更新质量数据
      this.qualityTestData.lastTestTime = quality.timestamp;
      this.qualityTestData.latency = quality.latency;
      this.qualityTestData.quality = quality.quality;
      
      // 保存到历史记录
      this._addToTestHistory(quality);
      
      logger.info('网络质量测试完成（模拟）', quality);
      
      return quality;
    }
    
    // 测试所有端点并计算平均延迟
    const endpoints = this.qualityTestData.testEndpoints;
    const results = [];
    
    for (const endpoint of endpoints) {
      try {
        const result = await this.testConnectivity(endpoint);
        if (result.success) {
          results.push(result.latency);
        }
      } catch (e) {
        logger.warn(`测试端点 ${endpoint} 失败`, e);
      }
    }
    
    // 计算平均延迟
    let avgLatency = -1;
    let success = false;
    
    if (results.length > 0) {
      avgLatency = Math.floor(results.reduce((sum, val) => sum + val, 0) / results.length);
      success = true;
    }
    
    // 评估质量
    const quality = this._evaluateNetworkQuality(avgLatency);
    
    // 构建结果
    const result = {
      latency: avgLatency,
      quality,
      success,
      timestamp: Date.now()
    };
    
    // 更新质量数据
    this.qualityTestData.lastTestTime = result.timestamp;
    this.qualityTestData.latency = avgLatency;
    this.qualityTestData.quality = quality;
    
    // 保存到历史记录
    this._addToTestHistory(result);
    
    logger.info('网络质量测试完成', result);
    
    return result;
  }

  /**
   * 评估网络质量
   * @param {number} latency 延迟（毫秒）
   * @returns {string} 网络质量等级
   * @private
   */
  _evaluateNetworkQuality(latency) {
    if (latency < 0) return NETWORK_QUALITY.BAD;
    if (latency < 100) return NETWORK_QUALITY.EXCELLENT;
    if (latency < 300) return NETWORK_QUALITY.GOOD;
    if (latency < 600) return NETWORK_QUALITY.FAIR;
    if (latency < 1000) return NETWORK_QUALITY.POOR;
    return NETWORK_QUALITY.BAD;
  }

  /**
   * 添加测试结果到历史记录
   * @param {Object} result 测试结果
   * @private
   */
  _addToTestHistory(result) {
    // 限制历史记录长度为20
    if (this.qualityTestData.testHistory.length >= 20) {
      this.qualityTestData.testHistory.shift();
    }
    
    this.qualityTestData.testHistory.push(result);
  }

  /**
   * 安全触发回调函数
   * @param {string} newNetworkType 新网络类型
   * @param {string} prevNetworkType 旧网络类型
   * @private
   */
  _triggerCallbacks(newNetworkType, prevNetworkType) {
    const callbackInfo = {
      networkType: newNetworkType,
      previousNetworkType: prevNetworkType,
      isConnected: newNetworkType !== 'none',
      quality: this.qualityTestData.quality,
      latency: this.qualityTestData.latency,
      timestamp: Date.now()
    };
    
    this.callbacks.forEach(callback => {
      try {
        if (typeof callback === 'function') {
          callback(newNetworkType, callbackInfo);
        }
      } catch (e) {
        logger.error('执行网络状态变化回调时出错', e);
      }
    });
  }

  /**
   * 停止监控网络状态变化
   */
  stopMonitoring() {
    if (!this.isMonitoring) return;
    
    // 取消监听
    wx.offNetworkStatusChange();
    
    // 标记为未监控
    this.isMonitoring = false;
    
    // 清空回调
    this.callbacks = [];
    
    // 停止质量测试定时器
    if (this.timers.qualityTest) {
      clearInterval(this.timers.qualityTest);
      this.timers.qualityTest = null;
    }
    
    logger.info('网络状态监控已停止');
  }

  /**
   * 添加网络状态变化回调
   * @param {Function} callback 回调函数
   */
  addCallback(callback) {
    if (typeof callback === 'function') {
      this.callbacks.push(callback);
    }
  }

  /**
   * 移除网络状态变化回调
   * @param {Function} callback 回调函数
   */
  removeCallback(callback) {
    const index = this.callbacks.indexOf(callback);
    if (index !== -1) {
      this.callbacks.splice(index, 1);
    }
  }

  /**
   * 获取当前网络类型
   * @private
   */
  _getNetworkType() {
    wx.getNetworkType({
      success: (res) => {
        const networkType = res.networkType;
        
        // 如果网络类型发生变化
        if (this.networkType !== networkType) {
          const prevNetworkType = this.networkType;
          this.networkType = networkType;
          
          logger.info(`初始网络类型: ${networkType}`);
          
          // 触发所有回调
          this._triggerCallbacks(networkType, prevNetworkType);
          
          // 如果启用了质量测试并且网络已连接，进行一次初始测试
          if (this.qualityTestData.isAutoTesting && networkType !== 'none') {
            this._testNetworkQuality().catch(err => {
              logger.error('初始网络质量测试失败', err);
            });
          }
        }
      },
      fail: (err) => {
        logger.error('获取网络类型失败', err);
      }
    });
  }

  /**
   * 获取当前网络类型
   * @returns {string} 网络类型
   */
  getNetworkType() {
    return this.networkType;
  }

  /**
   * 检查是否已连接网络
   * @returns {boolean} 是否已连接
   */
  isConnected() {
    return this.networkType !== 'none';
  }

  /**
   * 检查是否为WiFi网络
   * @returns {boolean} 是否为WiFi网络
   */
  isWifi() {
    return this.networkType === 'wifi';
  }

  /**
   * 检查是否为移动数据网络
   * @returns {boolean} 是否为移动数据网络
   */
  isMobile() {
    return ['2g', '3g', '4g', '5g'].includes(this.networkType);
  }

  /**
   * 获取当前网络质量
   * @returns {Object} 网络质量信息
   */
  getNetworkQuality() {
    return {
      quality: this.qualityTestData.quality,
      latency: this.qualityTestData.latency,
      lastTestTime: this.qualityTestData.lastTestTime,
      networkType: this.networkType
    };
  }

  /**
   * 手动测试网络质量
   * @returns {Promise<Object>} 测试结果
   */
  testNetworkQuality() {
    return this._testNetworkQuality();
  }

  /**
   * 获取网络质量历史记录
   * @returns {Array<Object>} 历史记录数组
   */
  getQualityHistory() {
    return [...this.qualityTestData.testHistory];
  }

  /**
   * 测试指定URL的连通性
   * @param {string} url 要测试的URL
   * @param {number} timeout 超时时间（毫秒）
   * @returns {Promise<Object>} 测试结果，包含success和latency字段
   */
  testConnectivity(url = 'https://www.baidu.com', timeout = 3000) {
    return new Promise((resolve) => {
      // 如果当前无网络，直接返回失败
      if (this.networkType === 'none') {
        resolve({ success: false, latency: -1, error: '无网络连接' });
        return;
      }
      
      // 在开发者工具中模拟连通性测试
      if (this.isDevTools) {
        setTimeout(() => {
          // 模拟各种网络环境下的延迟
          let latency = 100; // 默认良好延迟
          
          if (this.networkType === 'wifi') {
            latency = Math.floor(Math.random() * 100) + 50; // 50-150ms
          } else if (this.networkType === '4g' || this.networkType === '5g') {
            latency = Math.floor(Math.random() * 200) + 100; // 100-300ms
          } else if (this.networkType === '3g') {
            latency = Math.floor(Math.random() * 300) + 200; // 200-500ms
          } else if (this.networkType === '2g') {
            latency = Math.floor(Math.random() * 500) + 500; // 500-1000ms
          }
          
          resolve({ success: true, latency });
        }, 500);
        return;
      }
      
      // 记录开始时间
      const startTime = Date.now();
      
      // 发起请求
      const requestTask = wx.request({
        url,
        method: 'HEAD',
        timeout,
        success: () => {
          const latency = Date.now() - startTime;
          resolve({ success: true, latency });
        },
        fail: (err) => {
          resolve({ success: false, latency: -1, error: err.errMsg });
        }
      });
      
      // 设置超时处理
      setTimeout(() => {
        // 如果请求未结束，则中止请求
        requestTask.abort();
      }, timeout);
    });
  }
  
  /**
   * 获取适合当前网络的请求配置
   * @returns {Object} 请求配置
   */
  getOptimalRequestConfig() {
    // 根据网络类型和质量调整请求配置
    const config = {
      timeout: 30000, // 默认超时
      retryCount: 1,  // 默认重试次数
      retryDelay: 1000 // 默认重试延迟
    };
    
    // 根据网络类型调整
    if (this.networkType === 'wifi') {
      config.timeout = 15000;
      config.retryCount = 1;
      config.retryDelay = 500;
    } else if (this.networkType === '4g' || this.networkType === '5g') {
      config.timeout = 20000;
      config.retryCount = 2;
      config.retryDelay = 1000;
    } else if (this.networkType === '3g') {
      config.timeout = 25000;
      config.retryCount = 3;
      config.retryDelay = 2000;
    } else if (this.networkType === '2g') {
      config.timeout = 30000;
      config.retryCount = 3;
      config.retryDelay = 3000;
    }
    
    // 根据质量进一步调整
    if (this.qualityTestData.quality === NETWORK_QUALITY.EXCELLENT) {
      config.timeout = Math.max(10000, config.timeout - 5000);
      config.retryCount = Math.max(0, config.retryCount - 1);
    } else if (this.qualityTestData.quality === NETWORK_QUALITY.POOR || 
               this.qualityTestData.quality === NETWORK_QUALITY.BAD) {
      config.timeout = Math.min(40000, config.timeout + 10000);
      config.retryCount = Math.min(5, config.retryCount + 1);
      config.retryDelay = Math.min(5000, config.retryDelay * 1.5);
    }
    
    return config;
  }
}

// 导出网络质量枚举
NetworkManager.NETWORK_QUALITY = NETWORK_QUALITY;

// 导出单例
const networkManager = new NetworkManager();
module.exports = networkManager; 